﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Collections;
using System.Web.UI.WebControls;

namespace Acms.DataControls
{
    public class EventDrivenDataSource : DataSourceControl
    {
        public DataSourceView View { get; private set; }
        protected override DataSourceView GetView(string viewName)
        {
            if (View == null)
            {
                View = new EventDrivenDataSourceView(this);
            }
            return View;
        }

        public event EventHandler<EventDrivenDataSourceSelectEventArgs> Select;

        internal System.Collections.IEnumerable ExecuteSelect(DataSourceSelectArguments arguments)
        {
            if (Select != null)
            {
                EventDrivenDataSourceSelectEventArgs e = new EventDrivenDataSourceSelectEventArgs(arguments);
                Select(this, e);
                if(e.TotalRowCountSet)
                    arguments.TotalRowCount = e.TotalRowCount;
                return e.Data;
            }
            else
            {
                return null;
            }
        }

        public event EventHandler<EventDrivenDataSourcePerformOperationEventArgs> Delete;
        public event EventHandler<EventDrivenDataSourcePerformOperationEventArgs> Insert;
        public event EventHandler<EventDrivenDataSourcePerformOperationEventArgs> Update;

        internal int ExecuteOperation(EventDrivenDataSourcePerformOperationEventArgs.Operations operation, IDictionary keys, IDictionary values, IDictionary oldValues)
        {
            EventDrivenDataSourcePerformOperationEventArgs e = new EventDrivenDataSourcePerformOperationEventArgs(operation, keys, values, oldValues);
            switch(operation)
            {
                case EventDrivenDataSourcePerformOperationEventArgs.Operations.Insert:
                    if(Insert != null)
                    {
                        Insert(this, e);
                    }
                    break;
                case EventDrivenDataSourcePerformOperationEventArgs.Operations.Update:
                    if(Update != null)
                    {
                        Update(this, e);
                    }
                    break;
                case EventDrivenDataSourcePerformOperationEventArgs.Operations.Delete:
                    if(Delete != null)
                    {
                        Delete(this, e);
                    }
                    break;
            }
            return e.RowsChanged;
        }

        public bool CanInsert
        {
            get { return this.Insert != null; }
        }

        public bool CanUpdate
        {
            get { return this.Update != null; }
        }

        public bool CanDelete
        {
            get { return this.Delete != null; }
        }

        public bool CanPage { get; set; }
        public bool CanSort { get; set; }
        public bool CanRetrieveTotalRowCount { get; set; }

    }

    public class EventDrivenDataSourceView : DataSourceView
    {
        public EventDrivenDataSourceView(EventDrivenDataSource owner):base(owner, "")
        {
            this.Owner = owner;
        }

        public EventDrivenDataSource Owner { get; private set; }

        protected override System.Collections.IEnumerable ExecuteSelect(DataSourceSelectArguments arguments)
        {
            return Owner.ExecuteSelect(arguments);
        }

        protected override int ExecuteUpdate(IDictionary keys, IDictionary values, IDictionary oldValues)
        {
            return Owner.ExecuteOperation(EventDrivenDataSourcePerformOperationEventArgs.Operations.Update, keys, values, oldValues);
        }

        protected override int ExecuteDelete(IDictionary keys, IDictionary oldValues)
        {
            return Owner.ExecuteOperation(EventDrivenDataSourcePerformOperationEventArgs.Operations.Delete, keys, null, oldValues);
        }

        protected override int ExecuteInsert(IDictionary values)
        {
            return Owner.ExecuteOperation(EventDrivenDataSourcePerformOperationEventArgs.Operations.Insert, null, values, null);
        }

        public override bool CanDelete
        {
            get
            {
                return Owner.CanDelete;
            }
        }

        public override bool CanInsert
        {
            get
            {
                return Owner.CanInsert;
            }
        }

        public override bool CanPage
        {
            get
            {
                return Owner.CanPage;
            }
        }

        public override bool CanRetrieveTotalRowCount
        {
            get
            {
                return Owner.CanRetrieveTotalRowCount;
            }
        }

        public override bool CanSort
        {
            get
            {
                return Owner.CanSort;
            }
        }

        public override bool CanUpdate
        {
            get
            {
                return Owner.CanUpdate;
            }
        }
    }

    public class EventDrivenDataSourceSelectEventArgs : EventArgs
    {
        public EventDrivenDataSourceSelectEventArgs(DataSourceSelectArguments args)
        {
            this.SelectArguments = args;
        }

        public DataSourceSelectArguments SelectArguments{ get; private set; }
        public void SetData(IEnumerable data, int totalRowCount)
        {
            this.Data = data;
            this.TotalRowCount = totalRowCount;
            TotalRowCountSet = true;
        }
        
        public void SetData(IEnumerable data)
        {
            this.Data = data;
        }

        public void SetData(object data)
        {
            this.Data = new object[]{ data};
        }

        public IEnumerable Data { get; private set; }
        public int TotalRowCount { get; private set; }
        internal bool TotalRowCountSet { get; private set; }
    }

    public class EventDrivenDataSourcePerformOperationEventArgs : EventArgs
    {
        public enum Operations
        {
            Insert,
            Update,
            Delete
        }

        public EventDrivenDataSourcePerformOperationEventArgs(Operations operation, IDictionary keys, IDictionary values, IDictionary oldValues)
        {
            this.Operation = operation;
            this.Keys = keys;
            this.NewValues = values;
            this.OldValues = oldValues;
        }

        public Operations Operation { get; set; }
        public IDictionary Keys { get; set; }
        public IDictionary NewValues { get; set; }
        public IDictionary OldValues { get; set; }

        public int RowsChanged { get; set; }
    }
}
